home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / math / ast53src.zip / CHARTS2.C < prev    next >
C/C++ Source or Header  |  1996-09-29  |  31KB  |  894 lines

  1. /*
  2. ** Astrolog (Version 5.30) File: charts2.c
  3. **
  4. ** IMPORTANT NOTICE: The graphics database and chart display routines
  5. ** used in this program are Copyright (C) 1991-1996 by Walter D. Pullen
  6. ** (Astara@msn.com, http://www.magitech.com/~cruiser1/astrolog.htm).
  7. ** Permission is granted to freely use and distribute these routines
  8. ** provided one doesn't sell, restrict, or profit from them in any way.
  9. ** Modification is allowed provided these notices remain with any
  10. ** altered or edited versions of the program.
  11. **
  12. ** The main planetary calculation routines used in this program have
  13. ** been Copyrighted and the core of this program is basically a
  14. ** conversion to C of the routines created by James Neely as listed in
  15. ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
  16. ** available from Matrix Software. The copyright gives us permission to
  17. ** use the routines for personal use but not to sell them or profit from
  18. ** them in any way.
  19. **
  20. ** The PostScript code within the core graphics routines are programmed
  21. ** and Copyright (C) 1992-1993 by Brian D. Willoughby
  22. ** (brianw@sounds.wa.com). Conditions are identical to those above.
  23. **
  24. ** The extended accurate ephemeris databases and formulas are from the
  25. ** calculation routines in the program "Placalc" and are programmed and
  26. ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
  27. ** (alois@azur.ch). The use of that source code is subject to
  28. ** regulations made by Astrodienst Zurich, and the code is not in the
  29. ** public domain. This copyright notice must not be changed or removed
  30. ** by any user of this program.
  31. **
  32. ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
  33. ** X Window graphics initially programmed 10/23-29/1991.
  34. ** PostScript graphics initially programmed 11/29-30/1992.
  35. ** Last code change made 9/22/1996.
  36. */
  37.  
  38. #include "astrolog.h"
  39.  
  40.  
  41. /*
  42. ******************************************************************************
  43. ** Dual Chart Display Routines.
  44. ******************************************************************************
  45. */
  46.  
  47. /* Print out an aspect (or midpoint if -g0 switch in effect) grid of a      */
  48. /* relationship chart. This is similar to the ChartGrid() routine; however, */
  49. /* here we have both axes labeled with the planets for the two charts in    */
  50. /* question, instead of just a diagonal down the center for only one chart. */
  51.  
  52. void ChartGridRelation()
  53. {
  54.   char sz[cchSzDef];
  55.   int i, j, k, tot = cObj, temp;
  56.  
  57. #ifdef INTERPRET
  58.   if (us.fInterpret && !us.fGridConfig) {
  59.     InterpretGridRelation();
  60.     return;
  61.   }
  62. #endif
  63.   PrintSz(" 2>");
  64.   for (temp = 0, i = 1; i <= cObj; i++) if (!ignore[i]) {
  65.     PrintCh(chV);
  66.     AnsiColor(kObjA[i]);
  67.     sprintf(sz, "%c%c%c", chObj3(i)); PrintSz(sz);
  68.     AnsiColor(kDefault);
  69.     temp++;
  70.   }
  71.   PrintSz("\n1  ");
  72.   for (i = 1; i <= tot; i++) if (!ignore[i]) {
  73.     PrintCh(chV);
  74.     AnsiColor(kSignA(SFromZ(cp2.obj[i])));
  75.     sprintf(sz, "%2d%c", (int)cp2.obj[i] % 30, chDeg0); PrintSz(sz);
  76.     AnsiColor(kDefault);
  77.   }
  78.   PrintSz("\nV  ");
  79.   for (i = 1; i <= tot; i++) if (!ignore[i]) {
  80.     PrintCh(chV);
  81.     temp = SFromZ(cp2.obj[i]);
  82.     AnsiColor(kSignA(temp));
  83.     sprintf(sz, "%c%c%c", chSig3(temp)); PrintSz(sz);
  84.     AnsiColor(kDefault);
  85.   }
  86.   PrintL();
  87.   for (j = 1; j <= cObj; j++) if (!ignore[j])
  88.     for (k = 1; k <= 4; k++) {
  89.       if (k < 2)
  90.         PrintTab(chH, 3);
  91.       else if (k == 2) {
  92.         AnsiColor(kObjA[j]);
  93.         sprintf(sz, "%c%c%c", chObj3(j)); PrintSz(sz);
  94.       } else {
  95.         temp = SFromZ(cp1.obj[j]);
  96.         AnsiColor(kSignA(temp));
  97.         if (k == 3)
  98.           sprintf(sz, "%2d%c", (int)cp1.obj[j] - (temp-1)*30, chDeg0);
  99.         else
  100.           sprintf(sz, "%c%c%c", chSig3(temp));
  101.         PrintSz(sz);
  102.       }
  103.       if (k > 1)
  104.         AnsiColor(kDefault);
  105.       for (i = 1; i <= tot; i++) if (!ignore[i]) {
  106.         PrintCh((char)(k < 2 ? chC : chV));
  107.         temp = grid->n[i][j];
  108.         if (k > 1) {
  109.           if (i == j)
  110.             AnsiColor(kReverse);
  111.           AnsiColor(us.fGridConfig ? kSignA(temp) :
  112.             kAspA[temp]);
  113.         }
  114.         if (k < 2)
  115.           PrintTab(chH, 3);
  116.         else if (k == 2) {
  117.           if (us.fGridConfig)
  118.             sprintf(sz, "%c%c%c", chSig3(temp));
  119.           else
  120.             sprintf(sz, "%s", temp ? szAspectAbbrev[temp] : "   ");
  121.           PrintSz(sz);
  122.         } else if (k == 3) {
  123.           if (us.fGridConfig) {
  124.             sprintf(sz, "%2d%c", grid->v[i][j]/60, chDeg0); PrintSz(sz);
  125.           } else
  126.             if (grid->n[i][j]) {
  127.               if (grid->v[i][j] < 6000)
  128.                 sprintf(sz, "%c%2d", us.fAppSep ?
  129.                   (grid->v[i][j] < 0 ? 'a' : 's') :
  130.                   (grid->v[i][j] < 0 ? '-' : '+'), abs(grid->v[i][j])/60);
  131.               else
  132.                 sprintf(sz, "%3d", abs(temp)/60);
  133.               PrintSz(sz);
  134.             } else
  135.               PrintSz("   ");
  136.         } else {
  137.           if (grid->n[i][j]) {
  138.             sprintf(sz, "%02d'", abs(grid->v[i][j])%60); PrintSz(sz);
  139.           } else
  140.             PrintSz("   ");
  141.         }
  142.         AnsiColor(kDefault);
  143.       }
  144.       PrintL();
  145.     }
  146. }
  147.  
  148.  
  149. /* Display all aspects between objects in the relationship comparison chart, */
  150. /* one per line, in sorted order based on the total "power" of the aspects,  */
  151. /* as specified with the -r0 -a switch combination.                          */
  152.  
  153. void ChartAspectRelation()
  154. {
  155.   int ca[cAspect + 1], co[objMax];
  156.   char sz[cchSzDef];
  157.   int pcut = 30000, icut, jcut, phi, ihi, jhi, ahi, p, i, j, k, count = 0;
  158.   real ip, jp, rPowSum = 0.0;
  159.  
  160.   ClearB((lpbyte)ca, (cAspect + 1)*(int)sizeof(int));
  161.   ClearB((lpbyte)co, objMax*(int)sizeof(int));
  162.   loop {
  163.     phi = -1;
  164.  
  165.     /* Search for the next most powerful aspect in the aspect grid. */
  166.  
  167.     for (i = 0; i <= cObj; i++) if (!FIgnore(i))
  168.       for (j = 0; j <= cObj; j++) if (!FIgnore(j))
  169.         if (k = grid->n[i][j]) {
  170.           ip = i <= oNorm ? rObjInf[i] : 2.5;
  171.           jp = j <= oNorm ? rObjInf[j] : 2.5;
  172.           p = (int)(rAspInf[k]*(ip+jp)/2.0*
  173.             (1.0-RAbs((real)(grid->v[i][j]))/60.0/GetOrb(i, j, k))*1000.0);
  174.           if ((p < pcut || (p == pcut && (i > icut ||
  175.             (i == icut && j > jcut)))) && p > phi) {
  176.             ihi = i; jhi = j; phi = p; ahi = k;
  177.           }
  178.         }
  179.     if (phi < 0)    /* Exit when no less powerful aspect found. */
  180.       break;
  181.     pcut = phi; icut = ihi; jcut = jhi;
  182.     count++;                              /* Display the current aspect.   */
  183. #ifdef INTERPRET
  184.     if (us.fInterpret) {                  /* Interpret it if -I in effect. */
  185.       InterpretAspectRelation(jhi, ihi);
  186.       continue;
  187.     }
  188. #endif
  189.     rPowSum += (real)phi/1000.0;
  190.     ca[ahi]++;
  191.     co[jhi]++; co[ihi]++;
  192.     sprintf(sz, "%3d: ", count); PrintSz(sz);
  193.     PrintAspect(jhi, SFromZ(cp1.obj[jhi]), (int)RSgn(cp1.dir[jhi]), ahi,
  194.       ihi, SFromZ(cp2.obj[ihi]), (int)RSgn(cp2.dir[ihi]), 'A');
  195.     k = grid->v[ihi][jhi];
  196.     AnsiColor(k < 0 ? kWhite : kLtGray);
  197.     sprintf(sz, "- orb: %c%d,%02d'",
  198.       us.fAppSep ? (k < 0 ? 'a' : 's') : (k < 0 ? '-' : '+'),
  199.       abs(k)/60, abs(k)%60); PrintSz(sz);
  200.     AnsiColor(kDkGreen);
  201.     sprintf(sz, " - power:%6.2f\n", (real)phi/1000.0); PrintSz(sz);
  202.     AnsiColor(kDefault);
  203.   }
  204.  
  205.   PrintAspectSummary(ca, co, count, rPowSum);
  206. }
  207.  
  208.  
  209. /* Display locations of all midpoints between objects in the relationship */
  210. /* comparison chart, one per line, in sorted zodiac order from zero Aries */
  211. /* onward, as specified with the -r0 -m switch combination.               */
  212.  
  213. void ChartMidpointRelation()
  214. {
  215.   int cs[cSign + 1];
  216.   char sz[cchSzDef];
  217.   int mcut = -1, icut, jcut, mlo, ilo, jlo, m, i, j, count = 0;
  218.   long lSpanSum = 0;
  219.  
  220.   ClearB((lpbyte)cs, (cSign + 1)*(int)sizeof(int));
  221.   loop {
  222.     mlo = 21600;
  223.  
  224.     /* Search for the next closest midpoint farther down in the zodiac. */
  225.  
  226.     for (i = 0; i <= cObj; i++) if (!FIgnore(i))
  227.       for (j = 0; j <= cObj; j++) if (!FIgnore(j)) {
  228.         m = (grid->n[j][i]-1)*30*60 + grid->v[j][i];
  229.         if ((m > mcut || (m == mcut && (i > icut ||
  230.           (i == icut && j > jcut)))) && m < mlo) {
  231.           ilo = i; jlo = j; mlo = m;
  232.         }
  233.       }
  234.     if (mlo >= 21600)    /* Exit when no midpoint farther in zodiac found. */
  235.       break;
  236.     mcut = mlo; icut = ilo; jcut = jlo;
  237.     count++;                               /* Display the current midpoint. */
  238. #ifdef INTERPRET
  239.     if (us.fInterpret) {                   /* Interpret it if -I in effect. */
  240.       InterpretMidpointRelation(ilo, jlo);
  241.       continue;
  242.     }
  243. #endif
  244.     cs[mlo/60/30+1]++;
  245.     sprintf(sz, "%4d: ", count); PrintSz(sz);
  246.     PrintZodiac((real)mlo/60.0);
  247.     PrintCh(' ');
  248.     PrintAspect(ilo, SFromZ(cp1.obj[ilo]), (int)RSgn(cp1.dir[ilo]), 0,
  249.       jlo, SFromZ(cp2.obj[jlo]), (int)RSgn(cp2.dir[jlo]), 'M');
  250.     AnsiColor(kDefault);
  251.     m = (int)(MinDistance(cp1.obj[ilo], cp2.obj[jlo])*60.0);
  252.     lSpanSum += m;
  253.     sprintf(sz, "-%4d%c%02d' degree span.\n", m/60, chDeg1, m%60);
  254.     PrintSz(sz);
  255.   }
  256.  
  257.   PrintMidpointSummary(cs, count, lSpanSum);
  258. }
  259.  
  260.  
  261. /* Calculate any of the various kinds of relationship charts. This involves */
  262. /* computing and storing the planet and house positions for the "core" and  */
  263. /* "second" charts, and then combining them in the main single chart in the */
  264. /* proper manner, e.g. for synastry, composite, time space midpoint charts. */
  265.  
  266. void CastRelation()
  267. {
  268.   byte ignoreT[objMax];
  269.   int i;
  270.   real ratio, t1, t2, t;
  271.  
  272.   /* Cast the first chart. */
  273.  
  274.   ciMain = ciCore;
  275.   t1 = CastChart(fTrue);
  276.   cp1 = cp0;
  277.  
  278.   /* Cast the second chart. */
  279.  
  280.   ciCore = ciTwin;
  281.   if (us.nRel == rcTransit) {
  282.     for (i = 0; i <= cObj; i++) {
  283.       ignoreT[i] = ignore[i];
  284.       ignore[i] = ignore[i] && ignore2[i];
  285.     }
  286.   } else if (us.nRel == rcProgress) {
  287.     us.fProgress = fTrue;
  288.     is.JDp = MdytszToJulian(MM, DD, YY, TT, SS, ZZ);
  289.     ciCore = ciMain;
  290.   }
  291.   t2 = CastChart(fTrue);
  292.   if (us.nRel == rcTransit) {
  293.     for (i = 0; i <= cObj; i++)
  294.       ignore[i] = ignoreT[i];
  295.   } else if (us.nRel == rcProgress)
  296.     us.fProgress = fFalse;
  297.   cp2 = cp0;
  298.   ciCore = ciMain;
  299.  
  300.   /* Now combine the two charts based on what relation we are doing.   */
  301.   /* For the standard -r synastry chart, use the house cusps of chart1 */
  302.   /* and the planets positions of chart2.                              */
  303.  
  304.   ratio = (real)us.nRatio1 / ((real)(us.nRatio1 + us.nRatio2));
  305.   if (us.nRel <= rcSynastry) {
  306.     for (i = 1; i <= cSign; i++)
  307.       chouse[i] = cp1.cusp[i];
  308.  
  309.   /* For the -rc composite chart, take the midpoints of the planets/houses. */
  310.  
  311.   } else if (us.nRel == rcComposite) {
  312.     for (i = 0; i <= cObj; i++) {
  313.       planet[i] = Ratio(cp1.obj[i], cp2.obj[i], ratio);
  314.       if (RAbs(cp2.obj[i] - cp1.obj[i]) > rDegHalf)
  315.         planet[i] = Mod(planet[i] + rDegMax*ratio);
  316.       planetalt[i] = Ratio(cp1.alt[i], cp2.alt[i], ratio);
  317.       ret[i] = Ratio(cp1.dir[i], cp2.dir[i], ratio);
  318.     }
  319.     for (i = 1; i <= cSign; i++) {
  320.       chouse[i] = Ratio(cp1.cusp[i], cp2.cusp[i], ratio);
  321.       if (RAbs(cp2.cusp[i] - cp1.cusp[i]) > rDegHalf)
  322.         chouse[i] = Mod(chouse[i] + rDegMax*ratio);
  323.     }
  324.  
  325.     /* Make sure we don't have any 180 degree errors in house cusp    */
  326.     /* complement pairs, which may happen if the cusps are far apart. */
  327.  
  328.     for (i = 1; i <= cSign; i++)
  329.       if (MinDistance(chouse[sCap], Mod(chouse[i]-ZFromS(i+3))) > rDegQuad)
  330.         chouse[i] = Mod(chouse[i]+rDegHalf);
  331.     for (i = 1; i <= cSign; i++)
  332.       if (RAbs(MinDistance(chouse[i], planet[oAsc - 1 + i])) > rDegQuad)
  333.         planet[oAsc - 1 + i] = Mod(planet[oAsc - 1 + i]+rDegHalf);
  334.  
  335.   /* For the -rm time space midpoint chart, calculate the midpoint time and */
  336.   /* place between the two charts and then recast for the new chart info.   */
  337.  
  338.   } else if (us.nRel == rcMidpoint) {
  339.     is.T = Ratio(t1, t2, ratio);
  340.     t = (is.T*36525.0)+rRound; is.JD = RFloor(t)+2415020.0;
  341.     TT = RFract(t)*24.0;
  342.     ZZ = Ratio(DecToDeg(Zon), DecToDeg(ciTwin.zon), ratio);
  343.     SS = Ratio(DecToDeg(Dst), DecToDeg(ciTwin.dst), ratio);
  344.     TT -= ZZ - SS;
  345.     if (TT < 0.0) {
  346.       TT += 24.0; is.JD -= 1.0;
  347.     }
  348.     JulianToMdy(is.JD, &MM, &DD, &YY);
  349.     OO = Ratio(DecToDeg(Lon), DecToDeg(ciTwin.lon), ratio);
  350.     if (RAbs(ciTwin.lon-Lon) > rDegHalf)
  351.       OO = Mod(OO+rDegMax*ratio);
  352.     AA = Ratio(DecToDeg(Lat), DecToDeg(ciTwin.lat), ratio);
  353.     TT = DegToDec(TT); SS = DegToDec(SS); ZZ = DegToDec(ZZ);
  354.     OO = DegToDec(OO); AA = DegToDec(AA);
  355.     ciMain = ciCore;
  356.     CastChart(fTrue);
  357.  
  358.   /* There are a couple of non-astrological charts, which only require the */
  359.   /* number of days that have passed between the two charts to be done.    */
  360.  
  361.   } else
  362.     is.JD = RAbs(t2-t1)*36525.0;
  363.  
  364.   ComputeInHouses();
  365. }
  366.  
  367.  
  368. /*
  369. ******************************************************************************
  370. ** Other Chart Display Routines.
  371. ******************************************************************************
  372. */
  373.  
  374. /* Given two objects and an aspect between them, or an object and a sign  */
  375. /* that it's entering, print if this is a "major" event, such as a season */
  376. /* change or major lunar phase. This is called from the ChartInDay()      */
  377. /* searching and influence routines. Do an interpretation if need be too. */
  378.  
  379. void PrintInDay(source, aspect, dest)
  380. int source, aspect, dest;
  381. {
  382.   if (aspect == aSig) {
  383.     if (source == oSun) {
  384.       AnsiColor(kWhite);
  385.       if (dest == 1)
  386.         PrintSz(" (Vernal Equinox)");     /* If the Sun changes sign, */
  387.       else if (dest == 4)                 /* then print out if this   */
  388.         PrintSz(" (Summer Solstice)");    /* is a season change.      */
  389.       else if (dest == 7)
  390.         PrintSz(" (Autumnal Equinox)");
  391.       else if (dest == 10)
  392.         PrintSz(" (Winter Solstice)");
  393.     }
  394.   } else if (aspect > 0) {
  395.     if (source == oSun && dest == oMoo) {
  396.       if (aspect <= aSqu)
  397.         AnsiColor(kWhite);
  398.       if (aspect == aCon)
  399.         PrintSz(" (New Moon)");     /* Print out if the present */
  400.       else if (aspect == aOpp)      /* aspect is a New, Full,   */
  401.         PrintSz(" (Full Moon)");    /* or Half Moon.            */
  402.       else if (aspect == aSqu)
  403.         PrintSz(" (Half Moon)");
  404.     }
  405.   }
  406.   PrintL();
  407.  
  408. #ifdef INTERPRET
  409.   if (us.fInterpret)
  410.     InterpretInDay(source, aspect, dest);
  411. #endif
  412.   AnsiColor(kDefault);
  413. }
  414.  
  415.  
  416. /* Given two objects and an aspect (or one object, and an event such as a */
  417. /* sign or direction change) display the configuration in question. This  */
  418. /* is called by the many charts which list aspects among items, such as   */
  419. /* the -a aspect lists, -m midpoint lists, -d aspect in day search and    */
  420. /* influence charts, and -t transit search and influence charts.          */
  421.  
  422. void PrintAspect(obj1, sign1, ret1, asp, obj2, sign2, ret2, chart)
  423. int obj1, sign1, ret1, asp, obj2, sign2, ret2;
  424. char chart;
  425. {
  426.   char sz[cchSzDef];
  427.  
  428.   AnsiColor(kObjA[obj1]);
  429.   if (chart == 't' || chart == 'T')
  430.     PrintSz("trans ");
  431.   else if (chart == 'e' || chart == 'u' || chart == 'U')
  432.     PrintSz("progr ");
  433.   sprintf(sz, "%7.7s", szObjName[obj1]); PrintSz(sz);
  434.   AnsiColor(kSignA(sign1));
  435.   sprintf(sz, " %c%c%c%c%c",
  436.     ret1 > 0 ? '(' : (ret1 < 0 ? '[' : '<'), chSig3(sign1),
  437.     ret1 > 0 ? ')' : (ret1 < 0 ? ']' : '>')); PrintSz(sz);
  438.   AnsiColor(asp > 0 ? kAspA[asp] : kWhite);
  439.   PrintCh(' ');
  440.   if (asp == aSig)
  441.     sprintf(sz, "-->");                        /* Print a sign change. */
  442.   else if (asp == aDir)
  443.     sprintf(sz, "S/%c", obj2 ? chRet : 'D');   /* Print a direction change. */
  444.   else if (asp == 0)
  445.     sprintf(sz, chart == 'm' ? "&" : "with");
  446.   else
  447.     sprintf(sz, "%s", szAspectAbbrev[asp]);    /* Print an aspect. */
  448.   PrintSz(sz);
  449.   if (asp != aDir)
  450.     PrintCh(' ');
  451.   if (chart == 'A')
  452.     PrintSz("with ");
  453.   if (asp == aSig) {
  454.     AnsiColor(kSignA(obj2));
  455.     sprintf(sz, "%s", szSignName[obj2]); PrintSz(sz);
  456.   } else if (asp >= 0) {
  457.     AnsiColor(kSignA(sign2));
  458.     if (chart == 't' || chart == 'u' || chart == 'T' || chart == 'U')
  459.       PrintSz("natal ");
  460.     sprintf(sz, "%c%c%c%c%c ",
  461.       ret2 > 0 ? '(' : (ret2 < 0 ? '[' : '<'), chSig3(sign2),
  462.       ret2 > 0 ? ')' : (ret2 < 0 ? ']' : '>')); PrintSz(sz);
  463.     AnsiColor(kObjA[obj2]);
  464.     sprintf(sz, "%.10s", szObjName[obj2]); PrintSz(sz);
  465.   }
  466.   if (chart == 'D' || chart == 'T' || chart == 'U' ||
  467.     chart == 'a' || chart == 'A' || chart == 'm' || chart == 'M')
  468.     PrintTab(' ', 10-CchSz(szObjName[obj2]));
  469. }
  470.  
  471.  
  472. /* Based on the given chart information, display all the aspects taking   */
  473. /* place in the chart, as specified with the -D switch. The aspects are   */
  474. /* printed in order of influence determined by treating them as happening */
  475. /* outside among transiting planets, such that rare outer planet aspects  */
  476. /* are given more power than common ones among inner planets. (This is    */
  477. /* almost identical to the -a list, except the influences are different.) */
  478.  
  479. void ChartInDayInfluence()
  480. {
  481.   int source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY];
  482.   real power[MAXINDAY];
  483.   char sz[cchSzDef];
  484.   int occurcount = 0, i, j, k, l, m;
  485.  
  486.   /* Go compute the aspects in the chart. */
  487.  
  488.   i = us.fAppSep;
  489.   us.fAppSep = fTrue;     /* We always want applying vs. separating orbs. */
  490.   FCreateGrid(fFalse);
  491.   us.fAppSep = i;
  492.  
  493.   /* Search through the grid and build up the list of aspects. */
  494.  
  495.   for (j = 1; j <= cObj; j++) {
  496.     if (FIgnore(j))
  497.       continue;
  498.     for (i = 0; i < j; i++) {
  499.       if (FIgnore(i) || (k = grid->n[i][j]) == 0 || occurcount >= MAXINDAY)
  500.         continue;
  501.       source[occurcount] = i; aspect[occurcount] = k; dest[occurcount] = j;
  502.       l = grid->v[i][j];
  503.       power[occurcount] =
  504.         ((i <= oNorm ? rTransitInf[i] : 2.0)/4.0)*
  505.         ((j <= oNorm ? rTransitInf[j] : 2.0)/4.0)*
  506.         rAspInf[k]*(1.0-(real)abs(l)/60.0/GetOrb(i, j, k));
  507.       occurcount++;
  508.     }
  509.   }
  510.  
  511.   /* Sort aspects by order of influence. */
  512.  
  513.   for (i = 1; i < occurcount; i++) {
  514.     j = i-1;
  515.     while (j >= 0 && power[j] < power[j+1]) {
  516.       SwapN(source[j], source[j+1]);
  517.       SwapN(aspect[j], aspect[j+1]);
  518.       SwapN(dest[j], dest[j+1]);
  519.       SwapR(&power[j], &power[j+1]);
  520.       j--;
  521.     }
  522.   }
  523.  
  524.   /* Now display each aspect line. */
  525.  
  526.   for (i = 0; i < occurcount; i++) {
  527.     sprintf(sz, "%3d: ", i+1); PrintSz(sz);
  528.     j = source[i]; k = aspect[i]; l = dest[i];
  529.     PrintAspect(
  530.       j, SFromZ(planet[j]), (int)RSgn(ret[j]), k,
  531.       l, SFromZ(planet[l]), (int)RSgn(ret[l]), 'D');
  532.     m = grid->v[j][l];
  533.     AnsiColor(m < 0 ? kWhite : kLtGray);
  534.     sprintf(sz, "- %s%2d%c%02d'", m < 0 ? "app" : "sep",
  535.       abs(m)/60, chDeg1, abs(m)%60); PrintSz(sz);
  536.     AnsiColor(kDkGreen);
  537.     sprintf(sz, " - power:%6.2f", power[i]); PrintSz(sz);
  538.     PrintInDay(j, k, l);
  539.   }
  540.   if (occurcount == 0)
  541.     PrintSz("Empty transit aspect list.\n");
  542. }
  543.  
  544.  
  545. /* Given an arbitrary day, determine what aspects are made between this */
  546. /* transiting chart and the given natal chart, as specified with the -T */
  547. /* switch, and display the transits in order sorted by influence.       */
  548.  
  549. void ChartTransitInfluence(fProg)
  550. bool fProg;
  551. {
  552.   int source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY];
  553.   real power[MAXINDAY];
  554.   byte ignore3[objMax];
  555.   char sz[cchSzDef];
  556.   int occurcount = 0, fProgress = us.fProgress, i, j, k, l, m;
  557.  
  558.   /* Cast the natal and transiting charts as with a relationship chart. */
  559.  
  560.   cp1 = cp0;
  561.   for (i = 0; i <= cObj; i++) {
  562.     ignore3[i] = ignore[i]; ignore[i] = ignore2[i];
  563.   }
  564.   SetCI(ciCore, ciTran.mon, ciTran.day, ciTran.yea, Tim,
  565.     Dst, Zon, Lon, Lat);
  566.   if (us.fProgress = fProg) {
  567.     is.JDp = MdytszToJulian(MM, DD, YY, TT, SS, ZZ);
  568.     ciCore = ciMain;
  569.   }
  570.   CastChart(fTrue);
  571.   cp2 = cp0;
  572.   for (i = 0; i <= cObj; i++) {
  573.     ignore[i] = ignore3[i];
  574.   }
  575.  
  576.   /* Do a relationship aspect grid to get the transits. We have to make and */
  577.   /* restore three changes to get it right for this chart. (1) We make the  */
  578.   /* natal planets have zero velocity so applying vs. separating is only a  */
  579.   /* function of the transiter. (2) We force applying vs. separating orbs   */
  580.   /* regardless if -ga or -ma is in effect or not. (3) Finally we tweak the */
  581.   /* main restrictions to allow for transiting objects not restricted.      */
  582.  
  583.   for (i = 0; i <= cObj; i++) {
  584.     ret[i] = cp1.dir[i];
  585.     cp1.dir[i] = 0.0;
  586.     ignore3[i] = ignore[i];
  587.     ignore[i] = ignore[i] && ignore2[i];
  588.   }
  589.   i = us.fAppSep; us.fAppSep = fTrue;
  590.   FCreateGridRelation(fFalse);
  591.   us.fAppSep = i;
  592.   for (i = 0; i <= cObj; i++) {
  593.     cp1.dir[i] = ret[i];
  594.     ignore[i] = ignore3[i];
  595.   }
  596.  
  597.   /* Loop through the grid, and build up a list of the valid transits. */
  598.  
  599.   for (i = 0; i <= oNorm; i++) {
  600.     if (FIgnore2(i))
  601.       continue;
  602.     for (j = 0; j <= cObj; j++) {
  603.       if (FIgnore(j) || (is.fReturn && i != j) || (k = grid->n[i][j]) == 0 ||
  604.         occurcount >= MAXINDAY)
  605.         continue;
  606.       source[occurcount] = i; aspect[occurcount] = k; dest[occurcount] = j;
  607.       l = grid->v[i][j];
  608.       power[occurcount] = rTransitInf[i]*
  609.         ((j <= oNorm ? rObjInf[j] : 2.0)/4.0)*rAspInf[k]*
  610.         (1.0-(real)abs(l)/60.0/GetOrb(i, j, k));
  611.       occurcount++;
  612.     }
  613.   }
  614.  
  615.   /* After all transits located, sort them by their total power. */
  616.  
  617.   for (i = 1; i < occurcount; i++) {
  618.     j = i-1;
  619.     while (j >= 0 && power[j] < power[j+1]) {
  620.       SwapN(source[j], source[j+1]);
  621.       SwapN(aspect[j], aspect[j+1]);
  622.       SwapN(dest[j], dest[j+1]);
  623.       SwapR(&power[j], &power[j+1]);
  624.       j--;
  625.     }
  626.   }
  627.  
  628.   /* Now loop through list and display each transit in effect at the time. */
  629.  
  630.   for (i = 0; i < occurcount; i++) {
  631.     k = aspect[i];
  632.     l = source[i];
  633.     sprintf(sz, "%3d: ", i+1); PrintSz(sz);
  634.     j = SFromZ(cp2.obj[l]);
  635.     PrintAspect(l, j, (int)RSgn(cp2.dir[l]), k,
  636.       dest[i], SFromZ(cp1.obj[dest[i]]), (int)RSgn(cp1.dir[dest[i]]),
  637.       (char)(fProg ? 'U' : 'T'));
  638.     m = grid->v[l][dest[i]];
  639.     AnsiColor(m < 0 ? kWhite : kLtGray);
  640.     sprintf(sz, "- %s%2d%c%02d'", m < 0 ? "app" : "sep",
  641.       abs(m)/60, chDeg1, abs(m)%60); PrintSz(sz);
  642.     AnsiColor(kDkGreen);
  643.     sprintf(sz, " - power:%6.2f", power[i]); PrintSz(sz);
  644.     if (k == aCon && l == dest[i]) {    /* Print a small "R" for returns. */
  645.       AnsiColor(kWhite);
  646.       PrintSz(" R");
  647.     }
  648.     PrintL();
  649. #ifdef INTERPRET
  650.     if (us.fInterpret)
  651.       InterpretTransit(l, k, dest[i]);
  652. #endif
  653.     AnsiColor(kDefault);
  654.   }
  655.   if (occurcount == 0)
  656.     PrintSz("Empty transit list.\n");
  657.   us.fProgress = fProgress;
  658.   ciCore = ciMain;
  659.   CastChart(fTrue);
  660. }
  661.  
  662.  
  663. /* Given the zodiac location of a planet in the sky and its declination,   */
  664. /* and a location on the Earth, compute the azimuth and altitude of where  */
  665. /* on the local horizon sky the planet would appear to one at the given    */
  666. /* location. A reference MC position at Greenwich is also needed for this. */
  667.  
  668. void EclToHorizon(azi, alt, obj, objalt, lon, lat, mc)
  669. real *azi, *alt, obj, objalt, lon, lat, mc;
  670. {
  671.   real lonz, latz;
  672.  
  673.   lonz = RFromD(obj); latz = RFromD(objalt);
  674.   EclToEqu(&lonz, &latz);
  675.   lonz = RFromD(Mod(DFromR(mc-lonz+lon)));
  676.   lonz = RFromD(Mod(DFromR(lonz-lon+rPiHalf)));
  677.   EquToLocal(&lonz, &latz, rPiHalf-lat);
  678.   *azi = rDegMax-DFromR(lonz); *alt = DFromR(latz);
  679. }
  680.  
  681.  
  682. /* Display a calendar for the given month in the chart, as specified with  */
  683. /* with the -K switch. When color is on, the title is white, weekends are  */
  684. /* highlighted in red, and the specific day in the chart is colored green. */
  685.  
  686. void ChartCalendarMonth()
  687. {
  688.   char sz[cchSzDef];
  689.   int i, j, k;
  690.  
  691.   AnsiColor(kWhite);
  692.   PrintTab(' ', 16-CchSz(szMonth[Mon]) >> 1);
  693.   sprintf(sz, "%s%5d\n", szMonth[Mon], Yea); PrintSz(sz);
  694.   for (i = 0; i < cWeek; i++) {
  695.     sprintf(sz, "%c%c%c", szDay[i][0], szDay[i][1], i < cWeek-1 ? ' ' : '\n');
  696.     PrintSz(sz);
  697.   }
  698.   j = DayOfWeek(Mon, 1, Yea);
  699.   AnsiColor(kDefault);
  700.   for (i = 0; i < j; i++) {
  701.     if (i == 0)
  702.       AnsiColor(kRainbowA[1]);
  703.     PrintSz("-- ");
  704.     if (i == 0)
  705.       AnsiColor(kDefault);
  706.   }
  707.   k = DayInMonth(Mon, Yea);
  708.   for (i = 1; i <= k; i = AddDay(Mon, i, Yea, 1)) {
  709.     if (i == (int)Day)
  710.       AnsiColor(kRainbowA[4]);
  711.     else if (j == 0 || j == cWeek-1)
  712.       AnsiColor(kRainbowA[1]);
  713.     sprintf(sz, "%2d", i); PrintSz(sz);
  714.     if (j == 0 || j == cWeek-1 || i == Day)
  715.       AnsiColor(kDefault);
  716.     if (j < cWeek-1) {
  717.       j++;
  718.       PrintCh(' ');
  719.     } else {
  720.       j = 0;
  721.       PrintL();
  722.     }
  723.   }
  724.   while (j > 0 && j < cWeek) {
  725.     if (j == cWeek-1)
  726.       AnsiColor(kRainbowA[1]);
  727.     j++;
  728.     sprintf(sz, "--%c", j < cWeek ? ' ' : '\n'); PrintSz(sz);
  729.   }
  730.   AnsiColor(kDefault);
  731. }
  732.  
  733.  
  734. /* Display a calendar for the entire year given in the chart, as specified */
  735. /* with the -Ky switch. This is just like twelve of the individual month   */
  736. /* calendars above displayed together, with same color highlights and all. */
  737.  
  738. void ChartCalendarYear()
  739. {
  740.   char sz[cchSzDef];
  741.   int r, w, c, m, d, dy, p[3], l[3], n[3];
  742.  
  743.   dy = DayOfWeek(1, 1, Yea);
  744.   for (r = 0; r < 4; r++) {     /* Loop over one set of three months */
  745.     AnsiColor(kWhite);
  746.     for (c = 0; c < 3; c++) {
  747.       m = r*3+c+1;
  748.       PrintTab(' ', 16-CchSz(szMonth[m]) >> 1);
  749.       sprintf(sz, "%s%5d", szMonth[m], Yea); PrintSz(sz);
  750.       if (c < 2)
  751.         PrintTab(' ', 20 + MONTHSPACE -
  752.           (16-CchSz(szMonth[m]) >> 1) - CchSz(szMonth[m]) - 5);
  753.     }
  754.     PrintL();
  755.     for (c = 0; c < 3; c++) {
  756.       for (d = 0; d < cWeek; d++) {
  757.         sprintf(sz, "%c%c%c", szDay[d][0], szDay[d][1],
  758.           d < cWeek-1 || c < 2 ? ' ' : '\n'); PrintSz(sz);
  759.       }
  760.       if (c < 2)
  761.         PrintTab(' ', MONTHSPACE-1);
  762.       m = r*3+c+1;
  763.       p[c] = dy % cWeek;
  764.       l[c] = DayInMonth(m, Yea);
  765.       n[c] = 0;
  766.       dy += DaysInMonth(m, Yea);
  767.     }
  768.     for (w = 0; w < cWeek-1; w++) {    /* Loop over one set of week rows */
  769.       for (c = 0; c < 3; c++) {        /* Loop over one week in a month  */
  770.         m = r*3+c+1;
  771.         d = 0;
  772.         if (w == 0)
  773.           while (d < p[c]) {
  774.             if (d == 0)
  775.               AnsiColor(kRainbowA[1]);
  776.             PrintSz("-- ");
  777.             if (d == 0)
  778.               AnsiColor(kDefault);
  779.             d++;
  780.           }
  781.         AnsiColor(kDefault);
  782.         while (d < cWeek && n[c] < l[c]) {
  783.           n[c] = AddDay(m, n[c], Yea, 1);
  784.           if (n[c] == Day && m == Mon)
  785.             AnsiColor(kRainbowA[4]);
  786.           else if (d == 0 || d == cWeek-1)
  787.             AnsiColor(kRainbowA[1]);
  788.           sprintf(sz, "%2d%c", n[c], d < cWeek-1 || c < 2 ? ' ' : '\n');
  789.           PrintSz(sz);
  790.           if (d == 0 || d == cWeek-1 || (n[c] == Day && m == Mon))
  791.             AnsiColor(kDefault);
  792.           d++;
  793.         }
  794.         while (d < cWeek) {
  795.           if (d == 0 || d == cWeek-1)
  796.             AnsiColor(kRainbowA[1]);
  797.           sprintf(sz, "--%c", d < cWeek-1 || c < 2 ? ' ' : '\n'); PrintSz(sz);
  798.           if (d == 0)
  799.             AnsiColor(kDefault);
  800.           d++;
  801.         }
  802.         if (c < 2)
  803.           PrintTab(' ', MONTHSPACE-1);
  804.       }
  805.     }
  806.     if (r < 3)
  807.       PrintL();
  808.   }
  809.   AnsiColor(kDefault);
  810. }
  811.  
  812.  
  813. /* Display either a biorhythm chart or the time difference in various units */
  814. /* between two charts, i.e. two types of relationship "charts" that aren't  */
  815. /* related in any way to planetary positions, as specified by either the    */
  816. /* -rb or -rd switches, respectively.                                       */
  817.  
  818. void DisplayRelation()
  819. {
  820.   char sz[cchSzDef];
  821.   int i;
  822. #ifdef BIORHYTHM
  823.   int j;
  824.   real k, l;
  825. #endif
  826.  
  827.   /* If we are calculating the difference between two dates, then display */
  828.   /* the value and return, as with the -rd switch.                        */
  829.  
  830.   if (us.nRel == rcDifference) {
  831.     PrintSz("Differences between the dates in the two charts:\n");
  832.     for (i = 1; i <= 7; i++) {
  833.       AnsiColor(kRainbowA[i]);
  834.       switch (i) {
  835.       case 1: sprintf(sz, "Years  : %.0f", is.JD/365.25);      break;
  836.       case 2: sprintf(sz, "Months : %.0f", is.JD/(365.25/12)); break;
  837.       case 3: sprintf(sz, "Weeks  : %.0f", is.JD/7.0);         break;
  838.       case 4: sprintf(sz, "Days   : %.0f", is.JD);             break;
  839.       case 5: sprintf(sz, "Hours  : %.0f", is.JD*24.0);        break;
  840.       case 6: sprintf(sz, "Minutes: %.0f", is.JD*24.0*60.0);   break;
  841.       case 7: sprintf(sz, "Seconds: %.0f", is.JD*24.0*3600.0); break;
  842.       }
  843.       PrintSz(sz);
  844.       PrintL();
  845.     }
  846.     AnsiColor(kDefault);
  847.     return;
  848.   }
  849.  
  850. #ifdef BIORHYTHM
  851.   /* If we are doing a biorhythm (-rb switch), then we'll calculate it for */
  852.   /* someone born on the older date, at the time of the younger date. Loop */
  853.   /* through the week preceeding and following the date in question.       */
  854.  
  855.   is.JD = RFloor(is.JD + rRound);
  856.   for (is.JD -= (real)(us.nBioday/2), i = -us.nBioday/2; i <= us.nBioday/2;
  857.     i++, is.JD += 1.0) {
  858.     if (i == 0)
  859.       AnsiColor(kWhite);
  860.     else if (i == 1)
  861.       AnsiColor(kDefault);
  862.     j = abs(i);
  863.     sprintf(sz, "T%c%d%sDay%c:", i < 0 ? '-' : '+', j,
  864.       j < 10 ? " " : "", j != 1 ? 's' : ' '); PrintSz(sz);
  865.     for (j = 1; j <= 3; j++) {
  866.       PrintCh(' ');
  867.       switch (j) {
  868.       case 1: k = brPhy; AnsiColor(kRed);   PrintSz("Physical");     break;
  869.       case 2: k = brEmo; AnsiColor(kBlue);  PrintSz("Emotional");    break;
  870.       case 3: k = brInt; AnsiColor(kGreen); PrintSz("Intellectual"); break;
  871.       }
  872.       AnsiColor(i ? kDefault : kWhite);
  873.  
  874.       /* The biorhythm calculation is below. */
  875.  
  876.       l = RBiorhythm(is.JD, k);
  877.       sprintf(sz, " at %c%3.0f%%", l < 0.0 ? '-' : '+', RAbs(l)); PrintSz(sz);
  878.  
  879.       /* Print smiley face, medium face, or sad face based on current cycle. */
  880.  
  881.       AnsiColor(kPurple);
  882.       sprintf(sz, " :%c", l > 50.0 ? ')' : (l < -50.0 ? '(' : '|'));
  883.       PrintSz(sz);
  884.       AnsiColor(i ? kDefault : kWhite);
  885.       if (j < 3)
  886.         PrintCh(',');
  887.     }
  888.     PrintL();
  889.   }
  890. #endif /* BIORHYTHM */
  891. }
  892.  
  893. /* charts2.c */
  894.